package com.lmt.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Objects;

/**
 * AES加解密请求数据
 * Date 2018/07/20
 *
 * @author MT-Lin
 */
@SuppressWarnings("WeakerAccess")
public class AesRequestUtil {
    /**
     * 使用AES-128-CBC加密模式，key需要为16位,key和iv可以相同！
     */
    private static String KEY = "1234567890123456";

    private static String IV = "1234567890123456";


    /**
     * 加密方法
     * @param data  要加密的数据
     * @param key 加密key
     * @param iv 加密iv
     * @return 加密的结果
     * @throws Exception 异常
     */
    public static String encrypt(String data, String key, String iv) throws Exception {
        //noinspection SpellCheckingInspection
        // "算法/模式/补码方式 "NoPadding PkcsPadding
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        int blockSize = cipher.getBlockSize();

        byte[] dataBytes = data.getBytes();
        int plaintextLength = dataBytes.length;
        if (plaintextLength % blockSize != 0) {
            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
        }

        byte[] plaintext = new byte[plaintextLength];
        System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());

        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(plaintext);
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * 解密方法
     * @param data 要解密的数据
     * @param key  解密key
     * @param iv 解密iv
     * @return 解密的结果
     * @throws Exception 异常
     */
    public static String defaultAseDecrypt(String data, String key, String iv) throws Exception {
        byte[] encrypted1 = Base64.getDecoder().decode(data);

        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

        byte[] original = cipher.doFinal(encrypted1);
        return new String(original);
    }

    /**
     * 使用默认的key和iv加密
     * @param data 需要加密的数据
     * @return 加密后的数据
     * @throws Exception 异常
     */
    public static String defaultAseEncrypt(String data) throws Exception {
        return encrypt(data, KEY, IV);
    }

    /**
     * 使用默认的key和iv解密
     * @param data 需要解密的数据
     * @return 解密后的数据
     * @throws Exception 异常
     */
    public static String defaultAseDecrypt(String data) throws Exception {
        return defaultAseDecrypt(data, KEY, IV);
    }



    /**
     * 测试
     */
    public static void main(String[] args) throws Exception {

        String test1 = "{\"code\":1,\"data\":[{\"code\":\"002001\",\"creator\":\"1\",\"description\":\"职业是程序猿\",\"designation\":\"程序猿\",\"id\":\"4\",\"parentCode\":\"002\"}],\"message\":\"成功获取选项\"}";
        String test =new String(test1.getBytes(),"UTF-8");
        String data;
        String key =  KEY;
        String iv = IV;
        data = encrypt(test, key, iv);
        System.out.println("数据："+test);
        System.out.println("加密："+data);
        String trim = Objects.requireNonNull(defaultAseDecrypt(data, key, iv)).trim();
        System.out.println("解密："+trim);


    }
}
